package org.nokatag.system;


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.URL;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.noka.bver.CodeServer;
import org.noka.compressor.CssCompressor;
import org.noka.compressor.JavaScriptCompressor;
import org.noka.http.header.HttpHeaderSet;
import org.noka.select.SelectData;
import org.noka.tree.TreeData;
import org.nokatag.Connection.DBConnectionInit;
import org.nokatag.Connection.DBConnectionInterface;
import org.nokatag.code.ImageOutRequest;
import org.nokatag.dbgrid.AjaxSubGrid;
import org.nokatag.dbgrid.NDBGridDataServer;
import org.nokatag.elfunction.ELFunction;
import org.nokatag.jdom.Document;
import org.nokatag.jdom.Element;
import org.nokatag.jdom.input.SAXBuilder;
import org.nokatag.tagjava.GridStyle;
import org.nokatag.temp.MiniTemplator;
import org.nokatag.timer.NTimer;
import org.nokatag.timer.NTimerItem;


/**
 * @function Noka标签主控制器
 * @author rebin
 * @version Noka v5.0
 * @JDK      1.6.0
 */
public class NokaTagFilter implements Filter{
	private static String rootdir ="";	//系统根目录
	private static String language="language/";
	private static FilterConfig config=null;
	private static DBConnectionInterface connectionClass = null;
	private static List<NFilter> nokaFilter = null;//外部拦截器
	public void destroy() {
		if(nokaFilter!=null && !nokaFilter.isEmpty()){
			for(NFilter nfilter:nokaFilter){
				if(null!=nfilter && null!=nfilter.getFilter())
					nfilter.getFilter().destroy();
			}
		}
		Concest.TABLEMODEPATH=null;
		NokaContext.setContext(null);
	}
	/**
	 * 请求拦截
	 */
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) servletRequest;
		HttpServletResponse response = (HttpServletResponse) servletResponse;
		Connection noka_db_con = null;//数据库连接对象
		try{
			servletResponse.setCharacterEncoding(Concest.ENCODING);
			response.setCharacterEncoding(Concest.ENCODING);//编码初始化
		}catch (Exception ex){}
		try{
		//----------------设置编码类型--------------------------------
		servletRequest.setCharacterEncoding(Concest.ENCODING);
		request.setCharacterEncoding(Concest.ENCODING);//编码初始化
		}catch (Exception ex){}
		//-----------------request参数设置----------------------------
		NokaContext nContext = new NokaContext(new HashMap<String,Object>());
		NokaContext.setContext(nContext);
		nContext.put(ServletNokaContext.HTTP_REQUEST, request);
		nContext.put(ServletNokaContext.HTTP_RESPONSE, response);
		nContext.put(ServletNokaContext.HTTP_SESSION, request.getSession());
		nContext.put(ServletNokaContext.SERVLET_CONTEXT,config.getServletContext());
		//----------------设置输出协议头-----------------------------
		HttpHeaderSet hhs = new HttpHeaderSet();
		hhs.setHeader(request,response);
		try{
			lung(request);//语言文件初始化
			request.setAttribute("rootpath",rooturl(request));
			String resourcePath = RequestUtils.getServletPath(request);
	        if ("".equals(resourcePath) && null != request.getPathInfo()) {
	            resourcePath = request.getPathInfo();
	        }
			//-----------------初始化数据库连接----------------------------
			if(null!=connectionClass && DBConnectionInit.isSetCon(request)){
				noka_db_con = connectionClass.getConnection();
				nContext.put(ServletNokaContext.REQUEST_CONNECTION, noka_db_con);
			}
			//-----------------外部拦截器---------------------------------
			if(null!=nokaFilter && !nokaFilter.isEmpty()){
				for(NFilter nfilter:nokaFilter){
					try{
						if(null!=nfilter){
							Filter filter = nfilter.getFilter();
							String up = nfilter.getUrlPattern();
							if(null==filter){
								NLoadFun nloadFun = new NLoadFun();
								filter = (Filter)nloadFun.getBean(nfilter.getSfilter());
								nfilter.setFilte(filter);
							}
							if(null!=filter){
								if(null==up || resourcePath.startsWith(up)){
									NokaFilterChain nFilterChain = new NokaFilterChain();
									filter.doFilter(servletRequest, servletResponse, nFilterChain);
									if(!nFilterChain.IsContinue())
										return;//不向下执行
								}
							}
						}
					}catch(Exception se){
						se.printStackTrace();
					}
				}
			}
			//------------------------------------------------------------
			if (resourcePath.startsWith("/nokatag")) {//noka 处理
				try{
					String requestfilename = resourcePath.substring("/nokatag".length());
					if(requestfilename.endsWith(".fs")){
						FileUpload fup = new FileUpload();//文件上传处理
						fup.FileUtil(request, response,config);
					}else if(requestfilename.endsWith(".gridexcel")){//导出excel
						DataExcelOut oe=new DataExcelOut();
						oe.OutExcel(request,response,config);
					}else if(requestfilename.endsWith(".codeimg")){//验证码
						ImageOutRequest.outImage(request,response,config);
					}else if (requestfilename.endsWith(".codebver")){//滑动验证码
						CodeServer csv = new CodeServer();
						csv.CodeCreate(request, response);
					}else if(requestfilename.endsWith(".codebverjson")){//滑动json验证
						CodeServer csv = new CodeServer();
						csv.isCheckJSOn(request, response);
					}else if(requestfilename.endsWith(".itck")){//服务器验证
						ServerCheck(request,response);
					}else if(requestfilename.endsWith(".serfun")){//服务器方法调用
						SerFun(request,response);
					}else if(requestfilename.endsWith(".sgr")){//数据子表ajax加载
						AjaxSubGrid.newBody(request, response);
					}else if(requestfilename.endsWith(".statchart")){//图表
						StatFun(request,response);
					}else if(requestfilename.endsWith(".ndbgrid")){//数据表格
						NDBGridDataServer ndbserver = new NDBGridDataServer();
						ndbserver.dataRclass(request, response, config);
					}else if(requestfilename.endsWith(".tre")){//树形菜单ajax加载数据
						TreeData trdata = new TreeData();
						trdata.getData(request, response, config);
					}else if(requestfilename.endsWith(".select")){//下拉框
						SelectData trdata = new SelectData();
						trdata.getData(request, response, config);
					}else if(requestfilename.endsWith(".ajaxinput")){//ajaxinput
						SelectData trdata = new SelectData();
						trdata.getAjaxInputData(request, response, config);
					}else if(requestfilename.endsWith(".ajaxinputshows")){//ajaxinput
						SelectData trdata = new SelectData();
						trdata.getAjaxInputShows(request, response, config);
					}else{
						findStaticResource(requestfilename,request,response);//加载资源文件
					}
				}catch(Exception se){
					BugInfoWrint.Print(se);
					chain.doFilter(request, response);
				}
			}else if(IsInPrefix(resourcePath)) {//压缩处理,缓存处理
				String fna=resourcePath.substring(resourcePath.lastIndexOf("/")+1,resourcePath.length());
				if(Concest.EXTERNAL_CACHE_FILE_SKIP==null || Concest.EXTERNAL_CACHE_FILE_SKIP.indexOf(","+fna+",")==-1)// skip a.js,b.js
					findStaticResource(resourcePath,request,response);//加载资源文件
				else
					chain.doFilter(request, response);
			}else{
				chain.doFilter(request, response);
			}
		}finally{
			//-----------------------关闭连接--------------------------------
			if(null!=connectionClass){
				try{connectionClass.closeConnection(ServletNokaContext.getConnection());}catch(Exception se){}
				try{
					if(null!=Concest.CONNECTION && Concest.CONNECTION.toLowerCase().indexOf("hibernate")!=-1){
						DataUtil.ExceptionClear();
					}
				}catch(Exception se){}
			}
		}
	}
	/**
	 * 判断外部文目录是否需要缓存
	 * @param resourcePath
	 * @return
	 */
	private boolean IsInPrefix(String resourcePath){
		if(null!=Concest.EXTERNAL_CACHE_FILE_PREFIX){
			String[] prefixs = Concest.EXTERNAL_CACHE_FILE_PREFIX.split(",");
			for(String prefix:prefixs){
				if(resourcePath.startsWith(prefix)){
					return true;
				}
			}
		}
		return false;
	}
	/**
	 * 服务器验证
	 * @param request
	 */
	public void ServerCheck(HttpServletRequest request,HttpServletResponse response){
		String fun = request.getParameter("fun");
		String thisvalue = request.getParameter("thisvalue");
		if(fun!=null && fun.trim().length()>0){
			String rv=RunUserFunction.RunFunction(fun,thisvalue,request);
			try{
				OutputStream out = response.getOutputStream();
				Writer wr=new OutputStreamWriter(out,Concest.ENCODING);
				wr.write(rv);
				wr.flush();
				out.flush();
				wr.close();
				out.close();
			}catch(Exception e){
				BugInfoWrint.Print(e);
			}
		}
	}
	
	public void SerFun(HttpServletRequest request,HttpServletResponse response){
		String fun = request.getParameter("fun");
		if(fun!=null && fun.trim().length()>0){
			String rv=RunUserFunction.SerFunction(fun,request);
			try{
				OutputStream out = response.getOutputStream();
				Writer wr=new OutputStreamWriter(out,Concest.ENCODING);
				wr.write(rv);
				wr.flush();
				out.flush();
				wr.close();
				out.close();
			}catch(Exception e){
				BugInfoWrint.Print(e);
			}
		}
	}
	
	public void StatFun(HttpServletRequest request,HttpServletResponse response){
		String fun = request.getParameter("fun");
		if(fun!=null && fun.trim().length()>0){
			String rv=RunUserFunction.StatFunction(fun, request);
			try{
				OutputStream out = response.getOutputStream();
				Writer wr=new OutputStreamWriter(out,Concest.ENCODING);
				wr.write('\ufeff');//加载Bom
				wr.write(rv);
				wr.flush();
				out.flush();
				wr.close();
				out.close();
			}catch(Exception e){
				BugInfoWrint.Print(e);
			}
		}
	}
	
	/**
	 * 语言文件初始化
	 * @param request
	 */
	@SuppressWarnings("unchecked")
	public  void lung(HttpServletRequest request){
		try{
			Map<String,Object> rmap=langPath(request);
			if((!(Boolean)rmap.get("isCache")) && rmap.get("input")!=null){
				SAXBuilder saxbuilder = new SAXBuilder(); // 新建立构造器 
				Document doc = saxbuilder.build((InputStream)rmap.get("input"));//加载语言文件
				Element rootelementroot=doc.getRootElement(); 
				List<Element>  datalist = rootelementroot.getChildren("option");
				for(Element en:datalist){
					request.setAttribute(en.getAttributeValue("key"),en.getText());//其它常量
					Concest.LANGUAGE_CACHE.get((String)rmap.get("fp")).put(en.getAttributeValue("key"),en.getText());
				}
			}
			for (Map.Entry<String, String> m : Concest.PAGETEMP.entrySet()) {
				Concest.LANGUAGE_CACHE.get((String)rmap.get("fp")).put(m.getKey(), m.getValue());
			} 
		}catch(Exception se){
			//BugInfoWrint.Print(se);
		}
	}
	
	/**
	 * 初始化
	 */
	@SuppressWarnings("static-access")
	public void init(FilterConfig config) throws ServletException {
		NokaContext.setContext(null);
		System.out.println("=================noka tag init start============================");
		try{
			Concest.SYSTEM_START_TIME = new Date();
			//-------------------------------------------------------------
			this.config=config;
			rootdir = (config.getServletContext().getRealPath("/")).replace("\\", "/").replace("20%", " ").replace("%20", " ");//系统根目录
			String configpath = config.getInitParameter("config");//系统配置文件位置
			if(!rootdir.endsWith("/")){
				rootdir=rootdir+"/";
			}
			configpath = rootdir+configpath;
			System.out.println("noka config file path is:"+configpath);
			Concest.ROOTDIR = rootdir;
			Concest.TABLEMODEPATH=configpath;
			ConfigRead.ConfigInit(configpath);
			try{
				String filepath = Concest.FILESERVERPATH;
				File files = new File(filepath);
				files.mkdir();
			}catch(Exception se){
				
			}
			connectionClass = DBConnectionInit.getDBConnectionInterface(Concest.CONNECTION);//初始化数据库连接
			Concest.DB_MANAGER = connectionClass;
		}catch(Exception se){}
		System.out.println("=================noka tag init end============================");
		//--------------外部拦截器-----------------
		nokaFilterInit();
		//--------------初始化定时器---------------
		try{
			NTimer nTimer = NTimer.IniterNTimerItem();//初始化
			List<NTimerItem> timers = Concest.TIMER_ITEMS;
			for(NTimerItem nt:timers){
				nTimer.addTimer(nt);
			}
		}catch(Exception e){}
	}
	/**
	 * 外部拦截器
	 */
	private void nokaFilterInit(){
		if(null!=Concest.USER_FILTER && !Concest.USER_FILTER.isEmpty()){
			nokaFilter = new ArrayList<NFilter>();
			for(NFilter user_filter:Concest.USER_FILTER){
				try{
					Filter filter = null;
					String ufilter = user_filter.getSfilter();
					if(null!=ufilter){
						NLoadFun nloadFun = new NLoadFun();
						filter = (Filter)nloadFun.getBean(ufilter);
					}
					if(filter!=null){
						filter.init(config);
						user_filter.setFilte(filter);
						nokaFilter.add(user_filter);
					}else{
						user_filter.setFilte(null);
						nokaFilter.add(user_filter);
					}
				}catch(Exception se){
					se.printStackTrace();
				}
			}
		}
	}
	/**
	 * http 根路径
	 * @param request
	 * @return
	 */
	private  String rooturl(HttpServletRequest request){
		return ELFunction.rooturl(request);
	}
	/**
	 * 输出文件到网页上
	 * @param name
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	protected void findStaticResource(String name, HttpServletRequest request, HttpServletResponse response) throws IOException {
        if(name.indexOf(".")!=-1){
        	//------------------------------------------------------------------------------------
			String Prefixes=name.substring(name.lastIndexOf("."),name.length());//文件扩展名
			if(name.startsWith("/"))
				name=name.substring(1);
			InputStream input = findInputStream(request,name);//查找输入流
			//------------------------------------------------------------------------------------
	        String contentType = getContentType(Prefixes);
	        if (contentType != null) {
	          response.setContentType(contentType);
	        }
	        //-----------------------------------------------------------------------------------
	        Long lasttime = Concest.FILE_LAST_UPDATE_TIME.get(name);
	        if(lasttime!=null && isUpToDate(request,lasttime)){
	        	response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);//不需要更新
	        	return;
	        }
	        //-----------------------------------------------------------------------------------
	        response.setHeader("only-if-cached", "public");
	        String extension=Concest.CACHE_FILES.get("*"+Prefixes);//缓存期限
	        if(extension==null){
	        	extension=Concest.CACHE_FILES.get(name);//缓存期限
	        }
	        if(extension==null){
		        response.setHeader("Cache-Control", "public");
	        }else if(extension.endsWith("D")){//天为单位
	        	int d=Integer.parseInt(extension.substring(0,extension.length()-1));//天数
	        	long s=d*24*60*60;
	        	GregorianCalendar cal = new GregorianCalendar();
	        	cal.setTimeInMillis(lasttime==null?new Date().getTime():lasttime);
	        	cal.add(GregorianCalendar.DATE, d);//在日期上加d天
	        	response.setHeader("Cache-Control", "max-age="+s);
	        	response.setDateHeader("Expires", cal.getTimeInMillis());
	        }else if(extension.endsWith("h")){//小时为单位
	        	int h=Integer.parseInt(extension.substring(0,extension.length()-1));//小时
	        	long s=h*60*60;
	        	GregorianCalendar cal = new GregorianCalendar();
	        	cal.setTimeInMillis(lasttime==null?new Date().getTime():lasttime);
	        	cal.add(GregorianCalendar.HOUR, h);//在日期上加h小果
	        	response.setHeader("Cache-Control", "max-age="+s);
	        	response.setDateHeader("Expires", cal.getTimeInMillis());
	        }else if(extension.endsWith("s")){//秒为单位
	        	int s=Integer.parseInt(extension.substring(0,extension.length()-1));//秒
	        	GregorianCalendar cal = new GregorianCalendar();
	        	cal.setTimeInMillis(lasttime==null?new Date().getTime():lasttime);
	        	cal.add(GregorianCalendar.SECOND, s);//在日期上加s秒
	        	response.setHeader("Cache-Control", "max-age="+s);
	        	response.setDateHeader("Expires", cal.getTimeInMillis());
	        }else if(extension.endsWith("m")){//分为单位
	        	int m=Integer.parseInt(extension.substring(0,extension.length()-1));//分钟
	        	long s=m*60;
	        	GregorianCalendar cal = new GregorianCalendar();
	        	cal.setTimeInMillis(lasttime==null?new Date().getTime():lasttime);
	        	cal.add(GregorianCalendar.MINUTE, m);//在日期上加m分种
	        	response.setHeader("Cache-Control", "max-age="+s);
	        	response.setDateHeader("Expires", cal.getTimeInMillis());
	        }
	        if(lasttime!=null){
	        	response.setDateHeader(NHttpConstants.HEADER_LAST_MODIFIED, lasttime);
	        	response.setHeader(NHttpConstants.HEADER_ETAG, "\"" + lasttime + '\"');
	        }
	        //-----------------------------------------------------------------------------------
	        try {
	          copy(input, response.getOutputStream(),request,name);
	        } catch(Exception s){
	        	response.sendError(HttpServletResponse.SC_NOT_FOUND);//异常
	        }finally {
	        	if(input!=null)
	        		input.close();
	        }
        }
        
    }
	/**
	 * 文件输出类型
	 * @param name
	 * @return
	 */
	protected String getContentType(String name) {
        if (name.endsWith(".js")) {
            return "text/javascript";
        } else if (name.endsWith(".css")) {
            return "text/css";
        } else if (name.endsWith(".html")) {
            return "text/html";
        } else if (name.endsWith(".htm")) {
            return "text/html";
        }else if (name.endsWith(".txt")) {
            return "text/plain";
        } else if (name.endsWith(".gif")) {
            return "image/gif";
        } else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) {
            return "image/jpeg";
        } else if (name.endsWith(".png")) {
            return "image/png";
        } else {
            return null;
        }
    }
	//------判断文件是否为文本文件--------------------
	protected Boolean FileIsText(String name) {
        if (name.endsWith(".js")) {
            return true;
        } else if (name.endsWith(".css")) {
        	return true;
        } else if (name.endsWith(".html")) {
        	return true;
        } else if (name.endsWith(".htm")) {
        	return true;
        }else if (name.endsWith(".txt")) {
        	return true;
        } else if (name.endsWith(".gif")) {
            return false;
        } else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) {
            return false;
        } else if (name.endsWith(".png")) {
            return false;
        } else {
            return false;
        }
    }
	/**
	 * 文件拷贝输出
	 * @param input
	 * @param output
	 * @throws IOException
	 */
	 @SuppressWarnings("rawtypes")
	protected void copy(InputStream input, OutputStream output,HttpServletRequest request,String name) throws IOException {
	    try{
		 if(FileIsText(name)){
	    	 //---------------------------------------
	    	 MiniTemplator t = new MiniTemplator(input);
	    	 t.setVariable ("rootpath",rooturl(request));
	    	 //--------------替换文件上传的列表---------------------
	    	 String resourcePath = RequestUtils.getServletPath(request);
	         if ("".equals(resourcePath) && null != request.getPathInfo()) {
	             resourcePath = request.getPathInfo();
	         }
	 		 if (resourcePath.indexOf("/dbtable.html")!=-1 || resourcePath.indexOf("/upload.html")!=-1 || resourcePath.indexOf("/flash.html")!=-1) {//noka 处理
	 			if(resourcePath.indexOf("/dbtable.html")!=-1){
	 			 t.setVariable("datalist", FileUpload.filetable(request));
	 			}
	 			t.setVariable("nokadbgridcss", "<link type=\"text/css\" href=\""+rooturl(request)+"/"+Concest.PUBLIC_STYLE+"?v="+Concest.VERSION+"\" rel=\"stylesheet\">");
	 		 }
	    	 //-----------替换系统语言常量--------------------
	    	 Map<String,Object> rmap=langPath(request);
		     for(String key:Concest.LANGUAGE_CACHE.get((String)rmap.get("fp")).keySet()){
		    		 t.setVariable (key,Concest.LANGUAGE_CACHE.get((String)rmap.get("fp")).get(key));
		     }
		     //------------替换配置常量----------------------
		     for(ReValueDoc rd:Concest.REVALUELIST){
		    	 try{
			    	 if(rd.getType().equals(ReValueDoc.REQUEST))
			    		 try{t.setVariable (rd.getKey(),request.getAttribute(rd.getRevalue()).toString());}catch(Exception se){}
			    	 else if(rd.getType().equals(ReValueDoc.SESSION))
			    		 try{t.setVariable (rd.getKey(),request.getSession().getAttribute(rd.getRevalue()).toString());}catch(Exception se){}
			    	 else if(rd.getType().equals(ReValueDoc.CONST))
			    		 try{t.setVariable (rd.getKey(),rd.getRevalue());}catch(Exception se){}
			    	 else if(rd.getType().equals(ReValueDoc.PARAMENTER))
			    		 try{t.setVariable (rd.getKey(),request.getParameter(rd.getRevalue()));}catch(Exception se){}
		    	 }catch(Exception se){
		    	 }
		     }
		     //------------替换文件上传变量----------------
		     if(name.endsWith("upload.html") || name.endsWith("dbtable.html") || name.endsWith("flash.html")){
		    	 Enumeration enam=request.getParameterNames();
		    	 StringBuffer fileds = new StringBuffer();
				 while(enam.hasMoreElements()) {   
						String key =(String)enam.nextElement();
					    String value = request.getParameter(key);
					    fileds.append("<input type=\"hidden\" id = \""+key+"\" name=\""+key+"\"  value=\""+value+"\"/>");
				} 
				t.setVariable ("fileids",fileds.toString());
		     }
		     //-----------输出-----------------------------
		    try{ t.generateOutput(output);}catch(Exception e){}
	     }else{
	    	 final byte[] buffer = new byte[4096];
	         int n;
	         while (-1 != (n = input.read(buffer))) {
	             output.write(buffer, 0, n);
	         }
	     }
		 try{
		     output.flush();
			 output.close();
			 input.close();
		 }catch(Exception se){}
	    }catch(Exception se){
	    	 BugInfoWrint.Print(se);
	    }
	 }

	/**
	 * 查找文件
	 * @param request
	 * @param resourcePath
	 * @return
	 */
	protected InputStream findInputStream(HttpServletRequest request,String resourcePath){
		 try{
			if(resourcePath.startsWith("/"))
				resourcePath=resourcePath.substring(1);
			InputStream	fi= null;
			if(Concest.CACHE_FILE){
				if(Concest.FILE_CACHE.get(resourcePath)==null){
					if(resourcePath.endsWith("ndbgrid.css")){//生成css
						String css=GridStyle.GetStyle(Integer.parseInt(request.getParameter("syid")),request);
						fi=new ByteArrayInputStream(css.getBytes());
					}else if(resourcePath.endsWith("naccordion.css")){//生成css
						String css=GridStyle.GetStyle("accord",Integer.parseInt(request.getParameter("syid")),request);
						fi=new ByteArrayInputStream(css.getBytes());
					}else{
						try{
							URL sb =Thread.currentThread().getContextClassLoader().getResource(resourcePath);
							fi= sb.openStream();
						}catch(Exception se){}
					}
					//-----------外部文件处理---------------------
					if(fi==null){
						fi=new FileInputStream(rootdir+resourcePath);
					}
					//-----------压缩处理-------------------------
					ByteArrayOutputStream out=new ByteArrayOutputStream();
				    if((resourcePath.endsWith(".js") || resourcePath.endsWith(".JS")) && Concest.EXTERNAL_CACHE_FILE_JSZIP){//压缩
					    Reader in= new InputStreamReader(fi, Concest.ENCODING);
					    try{
					    JavaScriptCompressor compressor = new JavaScriptCompressor(in,null);
					    compressor.compress(out,-1, true, false,false, false);
					    }catch(Exception se){
					    	se.printStackTrace();
					    }
				    }else if((resourcePath.endsWith(".css") || resourcePath.endsWith(".CSS")) && Concest.EXTERNAL_CACHE_FILE_CSZIP){//压缩
				    	Reader in= new InputStreamReader(fi, Concest.ENCODING);
				    	CssCompressor css = new CssCompressor(in);
				    	css.compress(out, -1);
				    }else{
						final byte[] buffer = new byte[4096];
						int n;
						while (-1 != (n = fi.read(buffer))) {
							out.write(buffer, 0, n);
						}
						out.close();
						fi.close();
				     }
				     //------------------------------------------
					Concest.FILE_CACHE.put(resourcePath, out.toByteArray());
					Concest.FILE_LAST_UPDATE_TIME.put(resourcePath, new Date().getTime());
					BugInfoWrint.Print("重新生成内存文件："+resourcePath);
				}
				return new ByteArrayInputStream((byte[])Concest.FILE_CACHE.get(resourcePath));
			}else{
				if(resourcePath.endsWith("ndbgrid.css")){//生成css
					String css=GridStyle.GetStyle(Integer.parseInt(request.getParameter("syid")),request);
					fi=new ByteArrayInputStream(css.getBytes());
				}else if(resourcePath.endsWith("naccordion.css")){//生成css
					String css=GridStyle.GetStyle("accord",Integer.parseInt(request.getParameter("syid")),request);
					fi=new ByteArrayInputStream(css.getBytes());
				}else{
					try{
						URL sb =Thread.currentThread().getContextClassLoader().getResource(resourcePath);
						fi= sb.openStream();
					}catch(Exception se){}
				}
				if(fi==null){
					fi=new FileInputStream(rootdir+resourcePath);
				}
				return fi;
			}
		 }catch(Exception se){
			//BugInfoWrint.Print("findInputStream erro:"+resourcePath);
			//BugInfoWrint.Print(se);
		 }
	     return null;
	 }
	 //---------------------------语言文件选择--------------------------------------------
	 protected Map<String,Object> langPath(HttpServletRequest request){
		 Boolean isCache=false;
		 InputStream input =null;
		 Map<String,Object> remap=new HashMap<String,Object>();
		 String fp = "";
		 Concest.LANGUAGEPATH=language;
		 if(request.getHeader("accept-language")==null){//如果没有语言选择
			 fp=language+"language_"+Concest.DEFAULTLANGUAGE+".xml";
			 if(Concest.LANGUAGE_CACHE.get(fp)!=null){//已经有该语文件的缓存
				isCache=true;
			}else{
				input = findInputStream(request,fp);
				Concest.LANGUAGE_CACHE.put(fp,new HashMap<String,String>());
			}
		 }else{
		 	//---------------加载语言--------------------------------------------------
			String[] mark = request.getHeader("accept-language").split(",");//客户端语言//Accept-Language	zh-hans-CN,zh-CN;q=0.7,en-US;q=0.3
			for(String luang:mark){
				luang = luang.split(";")[0].toLowerCase();
				fp = language+"language_"+luang+".xml";
				if(Concest.LANGUAGE_CACHE.get(fp)!=null){//已经有该语文件的缓存
					isCache=true;
					break;
				}else{
					try{
						input = findInputStream(request,fp);//没有重新建立
						if(null!=input){
							Concest.LANGUAGE_CACHE.put(fp,new HashMap<String,String>());
							break;
						}
					}catch(Exception e){}
				}
			}
			if(!isCache && input==null){//默认加载语言
				fp=language+"language_"+Concest.DEFAULTLANGUAGE+".xml";
				if(Concest.LANGUAGE_CACHE.get(fp)!=null){//已经有该语文件的缓存
					isCache=true;
				}else{
					input = findInputStream(request,fp);
					Concest.LANGUAGE_CACHE.put(fp,new HashMap<String,String>());
				}
			}
		 }
		 remap.put("isCache", isCache);
		 remap.put("input", input);
		 remap.put("fp", fp);
		 return remap;
	 }
	 /**
	  * 是否需要更新
	  * @param req
	  * @param lastModified
	  * @return
	  */
	 protected boolean isUpToDate(HttpServletRequest req, Long lastModified)
	    {
		 	if(lastModified==null)
		 		return false;
	        String etag = "\"" + lastModified + '\"';
	        long modifiedSince = -1;
	        try
	        {
	            modifiedSince = req.getDateHeader(NHttpConstants.HEADER_IF_MODIFIED);
	        }
	        catch (RuntimeException ex)
	        {
	        }

	        if (modifiedSince != -1)
	        {
	            modifiedSince -= modifiedSince % 1000;
	        }
	        String givenEtag = req.getHeader(NHttpConstants.HEADER_IF_NONE);
	        if (givenEtag == null)
	        {
	            if (modifiedSince >= lastModified)
	            {
	                return true;
	            }
	            return false;
	        }
	        if (modifiedSince == -1)
	        {
	            if (!etag.equals(givenEtag))
	            {
	                return true;
	            }
	            return false;
	        }
	        if (etag.equals(givenEtag) || modifiedSince >= lastModified)
	        {
	            return true;
	        }
	        return false;
	    }
}

